home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -in_the_mag- / program_perfection / text.c < prev    next >
C/C++ Source or Header  |  1999-12-08  |  6KB  |  295 lines

  1. /*
  2.  * text.c
  3.  *
  4.  * Text class
  5.  *
  6.  * $Id :$
  7.  * $Log:$
  8.  *
  9.  */
  10.  
  11. #include "defs.h"
  12. #include "lines.h"
  13. #include "text.h"
  14. #include "memory.h"
  15. #include <clib/alib_protos.h>
  16.  
  17.  
  18. static LINE_PTR add_line( TEXT_PTR text, const STRPTR line_start, const STRPTR line_end, ERROR_TYPE *err );
  19.  
  20.  
  21. /*******************************************************************/
  22.  
  23. /*
  24.  * Text_New()
  25.  *
  26.  * PURPOSE: Constructor for text class
  27.  *
  28.  * INPUTS :
  29.  *
  30.  * RETURNS:
  31.  */
  32.  
  33. TEXT_PTR
  34. Text_New( const STRPTR contents, ERROR_TYPE *err_code )
  35. {
  36.     TEXT_PTR new_text;
  37.  
  38.     if( new_text = (TEXT_PTR) Memory_Alloc( sizeof( TEXT_TYPE ) ) )
  39.     {
  40.         NewList( (struct List *) &(new_text->Contents) );
  41.  
  42.         {
  43.             STRPTR current_char = contents;
  44.             STRPTR line_start   = contents;
  45.  
  46.             for( ; *current_char; current_char++ )
  47.             {
  48.                 switch( *current_char )
  49.                 {
  50.                     case '\n' :
  51.                     case '\f' :
  52.                         /* found a line break */
  53.                         if( add_line( new_text, line_start, current_char + 1, err_code ) )
  54.                             line_start = current_char + 1;
  55.                         else
  56.                             ;
  57.                     default:
  58.                         /* do nothing */
  59.                 }
  60.             } /* for */
  61.  
  62.             if( current_char != line_start )
  63.             {
  64.                 /* the last line didn't end in a break - so add it now */
  65.                 add_line( new_text, line_start, current_char + 1, err_code );
  66.             }
  67.         } /* block */
  68.  
  69.     } /* if */
  70.     else
  71.         *err_code = ERR_NO_MEMORY;
  72.  
  73.     return new_text;
  74. }
  75.  
  76. /*
  77.  * add_line()
  78.  *
  79.  * PURPOSE: add a line to a text object and bump line count
  80.  *
  81.  * INPUTS : text       - the text object
  82.  *          line_start - ptr to start of line
  83.  *          line_end   - ptr to end of line
  84.  *
  85.  * RETURNS: ptr to the new line if succcesful, NULL otherwise
  86.  *
  87.  */
  88.  
  89. static LINE_PTR
  90. add_line( TEXT_PTR text, const STRPTR line_start, const STRPTR line_end, ERROR_TYPE *err_code )
  91. {
  92.     LINE_PTR new_line = NULL;
  93.  
  94.     /* is the list full? */
  95.     if( text->Length < MAX_TEXT_LEN )
  96.     {
  97.         /* nope, still room */
  98.  
  99.         LINE_LEN_TYPE   len = line_end - line_start;
  100.  
  101.         if( new_line = Line_New( line_start, len, err_code ) )
  102.         {
  103.             AddTail( (struct List *) &(text->Contents), (struct Node *) &(new_line->Node) );
  104.             text->Length++;
  105.             if( len > text->MaxWidth ) text->MaxWidth = len;
  106.         }
  107.     }
  108.     else
  109.         /* */
  110.         *err_code = ERR_TOO_MANY_LINES;
  111.  
  112.     return new_line;
  113. }
  114.  
  115.  
  116. /*******************************************************************/
  117.  
  118. /*
  119.  * Text_Dispose()
  120.  *
  121.  * PURPOSE: Destructor for text class
  122.  *
  123.  * INPUTS:
  124.  *
  125.  * RETURNS: None
  126.  */
  127.  
  128. VOID
  129. Text_Dispose( TEXT_PTR text )
  130. {
  131.     LINE_PTR      l1 = (LINE_PTR) text->Contents.mlh_Head;
  132.     LINE_PTR      l2;
  133.     TEXT_LEN_TYPE i  = text->Length;
  134.  
  135.     for( ; i; i-- )
  136.     {
  137.         l2 = (LINE_PTR) l1->Node.mln_Succ;
  138.         Line_Dispose( l1 );
  139.         l1 = l2;
  140.     }
  141.  
  142.     Memory_Free( text, sizeof( TEXT_TYPE ) );
  143. }
  144.  
  145.  
  146. /*******************************************************************/
  147.  
  148. /*
  149.  * Text_GetTopLine()
  150.  *
  151.  * PURPOSE:
  152.  *
  153.  * INPUTS :
  154.  *
  155.  * RETURNS:
  156.  */
  157.  
  158. LINE_PTR
  159. Text_GetTopLine( const TEXT_PTR text )
  160. {
  161.     return text->Length ? (LINE_PTR) text->Contents.mlh_Head : NULL;
  162. }
  163.  
  164.  
  165. /*******************************************************************/
  166.  
  167. /*
  168.  * Text_GetBottomLine()
  169.  *
  170.  * PURPOSE:
  171.  *
  172.  * INPUTS :
  173.  *
  174.  * RETURNS:
  175.  */
  176.  
  177. LINE_PTR
  178. Text_GetBottomLine( const TEXT_PTR text )
  179. {
  180.     return text->Length ? (LINE_PTR) text->Contents.mlh_TailPred : NULL;
  181. }
  182.  
  183.  
  184. /*******************************************************************/
  185.  
  186. /*
  187.  * Text_GetNextLine()
  188.  *
  189.  * PURPOSE: Get next Line in a linked list of Line objects.
  190.  *
  191.  * INPUTS : line - the Line to find the successor of.
  192.  *
  193.  * RETURNS: pointer to the sucessor if there is one, else NULL
  194.  */
  195.  
  196. LINE_PTR
  197. Text_GetNextLine( const TEXT_PTR text, const LINE_PTR line )
  198. {
  199.     LINE_PTR l = (LINE_PTR) line->Node.mln_Succ;
  200.  
  201.     return (l->Node.mln_Succ) ? l : NULL;
  202. }
  203.  
  204.  
  205. /*******************************************************************/
  206.  
  207. /*
  208.  * Text_GetPrevLine()
  209.  *
  210.  * PURPOSE: Get previous Line in a linked list of Line objects.
  211.  *
  212.  * INPUTS : line - the Line to find the predecessor of.
  213.  *
  214.  * RETURNS: pointer to the predecessor if there is one, else NULL
  215.  */
  216.  
  217. LINE_PTR
  218. Text_GetPrevLine( const TEXT_PTR text, const LINE_PTR line )
  219. {
  220.     LINE_PTR l = (LINE_PTR) line->Node.mln_Pred;
  221.  
  222.     return l->Node.mln_Pred ? l : NULL;
  223. }
  224.  
  225.  
  226.  
  227. /*******************************************************************/
  228.  
  229. /*
  230.  * Text_GetNthLine()
  231.  *
  232.  * PURPOSE:
  233.  *
  234.  * INPUTS :
  235.  *
  236.  * RETURNS:
  237.  */
  238.  
  239. LINE_PTR
  240. Text_GetNthLine( const TEXT_PTR text, TEXT_LEN_TYPE line_no )
  241. {
  242.     LINE_PTR line = NULL;
  243.  
  244.     if( line_no < text->Length )
  245.     {
  246.         LINE_LEN_TYPE i = 0;
  247.         line = (LINE_PTR) text->Contents.mlh_Head;
  248.  
  249.         while( i++ < line_no )
  250.             line = (LINE_PTR) line->Node.mln_Succ;
  251.     }
  252.  
  253.     return line;
  254. }
  255.  
  256.  
  257. /*******************************************************************/
  258.  
  259. /*
  260.  * Text_GetLength()
  261.  *
  262.  * PURPOSE:
  263.  *
  264.  * INPUTS :
  265.  *
  266.  * RETURNS:
  267.  */
  268.  
  269. TEXT_LEN_TYPE
  270. Text_GetNoOfLines( const TEXT_PTR text )
  271. {
  272.     return text->Length;
  273. }
  274.  
  275.  
  276. /*******************************************************************/
  277.  
  278. /*
  279.  * Text_GetMaxWidth()
  280.  *
  281.  * PURPOSE:
  282.  *
  283.  * INPUTS :
  284.  *
  285.  * RETURNS:
  286.  */
  287.  
  288. LINE_LEN_TYPE
  289. Text_GetMaxWidth( const TEXT_PTR text )
  290. {
  291.     return text->MaxWidth;
  292. }
  293.  
  294.  
  295.